/**
 * \file adrv9009/src/app/headless.c
 *
 * \brief Contains example code for user integration with their application
 *
 * Copyright 2015-2017 Analog Devices Inc.
 * Released under the AD9378-AD9379 API license, for more information see the "LICENSE.txt" file in this zip file.
 *
 */

/****< Insert User Includes Here >***/

#include <stdio.h>



#include "adi_hal.h"
#include "talise.h"
#include "talise_config.h"
#include "jesd_core.h"

#include "app_parameters.h"
#include "app_clocking.h"
#include "app_talise.h"
#include "error.h"
#include "util.h"

#include "spi_extra.h"
#include "gpio_extra.h"

struct adi_hal hal;
taliseDevice_t tal;

/**********************************************************/
/********** Talise Data Structure Initializations *********/
/**********************************************************/
//int main()
int adrv9009_init(void)
{

	adiHalErr_t err;

	/****************************************************************************************
	 * compute the lane rate from profile settings
	 * lane_rate = input_rate * M * 20 / L
	 * where L and M are explained in taliseJesd204bFramerConfig_t comments
	 ****************************************************************************************/
	uint32_t rx_lane_rate_khz = talInit.rx.rxProfile.rxOutputRate_kHz *
				    talInit.jesd204Settings.framerA.M * (20 /
						    hweight8(talInit.jesd204Settings.framerA.serializerLanesEnabled));
	uint32_t rx_div40_rate_hz = rx_lane_rate_khz * (1000 / 40);
	uint32_t tx_lane_rate_khz = talInit.tx.txProfile.txInputRate_kHz *
				    talInit.jesd204Settings.deframerA.M * (20 /
						    hweight8(talInit.jesd204Settings.deframerA.deserializerLanesEnabled));
	uint32_t tx_div40_rate_hz = tx_lane_rate_khz * (1000 / 40);
	uint32_t rx_os_lane_rate_khz = talInit.obsRx.orxProfile.orxOutputRate_kHz *
				       talInit.jesd204Settings.framerB.M * (20 /
						       hweight8(talInit.jesd204Settings.framerB.serializerLanesEnabled));
	uint32_t rx_os_div40_rate_hz = rx_os_lane_rate_khz * (1000 / 40);

	/****************************************************************************************
	 * compute the local multiframe clock
	 * serializer:   lmfc_rate = (lane_rate * 100) / (K * F)
	 * deserializer: lmfc_rate = (lane_rate * 100) / (K * 2 * M / L)
	 * where K, F, L, M are explained in taliseJesd204bFramerConfig_t comments
	 ****************************************************************************************/
	uint32_t rx_lmfc_rate = (rx_lane_rate_khz * 100) /
				(talInit.jesd204Settings.framerA.K * talInit.jesd204Settings.framerA.F);
	uint32_t tx_lmfc_rate = (tx_lane_rate_khz * 100) /
				(talInit.jesd204Settings.deframerA.K * 2 * talInit.jesd204Settings.deframerA.M /
				 hweight8(talInit.jesd204Settings.deframerA.deserializerLanesEnabled));
	uint32_t rx_os_lmfc_rate = (rx_os_lane_rate_khz * 100) /
				   (talInit.jesd204Settings.framerB.K * talInit.jesd204Settings.framerB.F);

	uint32_t lmfc_rate = min(rx_lmfc_rate, rx_os_lmfc_rate);
	lmfc_rate = min(tx_lmfc_rate, lmfc_rate);

	xil_spi_init_param hal_spi_param = {
		.type = SPI_PS,
		.device_id = 0,
		.flags = SPI_CS_DECODE
	};
	struct xil_gpio_init_param hal_gpio_param = {
		.type = GPIO_PS,
		.device_id = GPIO_DEVICE_ID
	};
//	struct adi_hal hal;
//	taliseDevice_t tal;
	tal.devHalInfo = (void *) &hal;
	hal.extra_gpio= &hal_gpio_param;
	hal.extra_spi = &hal_spi_param;
	hal.gpio_adrv_resetb_num = ADRV9009_RESETB;
	hal.spi_adrv_csn = ADRV9009_CS;


	/**********************************************************/
	/************ Talise Initialization Sequence **************/
	/**********************************************************/

	/**********************************************************
	 * AD8528 Clock Setting
	 **********************************************************/
	err = clocking_init(rx_div40_rate_hz,
			    tx_div40_rate_hz,
			    rx_os_div40_rate_hz,
			    talInit.clocks.deviceClock_kHz,
			    lmfc_rate);
	if (err != ADIHAL_OK){
		printf("clocking_init failed ! \n");
	}else{
		printf("clocking_init OK ! \n");
	}

	mdelay(1000);

	/**********************************************************
	 * JESD204 IP Core Structure Setting
	 **********************************************************/
	tx_jesd.base_address = XPAR_JESD204_2_BASEADDR;
	rx_jesd.base_address = XPAR_JESD204_1_BASEADDR;
	tx_jesd.rx_tx_n = 0;
	tx_jesd.scramble_enable = 1;
	tx_jesd.octets_per_frame = 2;
	tx_jesd.frames_per_multiframe = 32;
	tx_jesd.subclass_mode = 1;
	rx_jesd.rx_tx_n = 1;
	rx_jesd.scramble_enable = 1;
	rx_jesd.octets_per_frame = 4;
	rx_jesd.frames_per_multiframe = 32;
	rx_jesd.subclass_mode = 1;
	jesd_array.tx_jesd = tx_jesd;
	jesd_array.rx_jesd = rx_jesd;
	jesd_array.orx_jesd = rx_jesd;
	jesd_array.orx_jesd.base_address = XPAR_JESD204_0_BASEADDR;

	/*********************************************************
	 * ADRV9009 HAL Setting
	 *********************************************************/
	err = talise_setup(&tal, &talInit);
	if (err != ADIHAL_OK){
		printf("talise setup failed !\n");
	}else{
		printf("talise setup OK !\n");
	}

	ADIHAL_sysrefReq(tal.devHalInfo, SYSREF_CONT_ON);

	return SUCCESS;
}

//talise_shutdown(&tal);
